package com.mojo.concurrent.concurrent_03_aqs;

import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Lock;

/**
 * AQS源码解析
 * <pre>
 * 什么是AQS? 为什么它是核心?
 *   构建锁和同步器框架，简单且高效地的实现同步器
 * AQS的核心思想是什么? 它是怎么实现的?底层数据结构等
 *   核心思想:如果被请求的共享资源空闲，则将当前请求资源的线程设置为有效的工作线程，并且将共享资源设置为锁定状态。
 * 如果被请求的共享资源被占用，那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制，这个机制AQS是用CLH(Craig,Landin,and Hagersten)队列锁实现的，即将暂时获取不到锁的线程加入到队列中
 * AQS有哪些核心的方法? AQS定义什么样的资源获取方式?
 *   AQS定义了两种资源获取方式：独占(只有一个线程能访问执行，又根据是否按队列的顺序分为公平锁和非公平锁，如ReentrantLock) 和共享(多个线程可同时访问执行，如Semaphore、CountDownLatch、 CyclicBarrier )。ReentrantReadWriteLock可以看成是组合式，允许多个线程同时对某一资源进行读。
 * AQS底层使用了什么样的设计模式?模板模式
 * AQS的应用示例?并发工具类里面Sync都实现了AQS
 * </pre>
 *
 * @author <a href="mailto:sjj@jianzhimao.com">mojo</a>
 * copyright (C), 2013-2022, 广州九尾信息科技有限公司
 * @date 2022/3/18 16:48
 */
public class AbstractQueuedSynchronizerDemo1 {

    // 自定义同步器
    static class Sync extends AbstractQueuedSynchronizer {
        //  尝试获取资源（独占方式）
        @Override
        protected boolean tryAcquire(int arg) {
            return super.tryAcquire(arg);
        }

        //  尝试释放资源（独占方式）
        @Override
        protected boolean tryRelease(int arg) {
            return super.tryRelease(arg);
        }

        //  尝试获取资源（共享方式）
        @Override
        protected int tryAcquireShared(int arg) {
            return super.tryAcquireShared(arg);
        }

        //  尝试释放资源（共享方式）
        @Override
        protected boolean tryReleaseShared(int arg) {
            return super.tryReleaseShared(arg);
        }

        // 该线程是否独占
        @Override
        protected boolean isHeldExclusively() {
            return super.isHeldExclusively();
        }
    }

    static class MyThread extends Thread {
        Lock lock;

        public MyThread(String name, Lock lock) {
            super(name);
            this.lock = lock;
        }

        @Override
        public void run() {
            lock.lock();
            try {
                System.out.println(Thread.currentThread() + " running");
            } finally {
                lock.unlock();
            }
        }

    }

    public static void main(String[] args) {
        Lock lock = new MutexLock();
        MyThread t1 = new MyThread("thread 1", lock);
        MyThread t2 = new MyThread("thread 2", lock);
        t1.start();
        t2.start();
    }
}

